package com.zbkj.crmeb.agent.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.common.CommonPage;
import com.crmeb.core.common.CommonResult;
import com.common.PageParamRequest;
import com.crmeb.core.exception.CrmebException;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zbkj.crmeb.agent.dao.AgentDao;
import com.zbkj.crmeb.agent.model.Agent;
import com.zbkj.crmeb.agent.model.AgentAccount;
import com.zbkj.crmeb.agent.request.AddAgentRequest;
import com.zbkj.crmeb.agent.request.AdminAgentRequest;
import com.zbkj.crmeb.agent.request.AgentListRequest;
import com.zbkj.crmeb.agent.request.SettlementRequest;
import com.zbkj.crmeb.agent.response.DropDownAgentsResponse;
import com.zbkj.crmeb.agent.response.SettlementResponse;
import com.zbkj.crmeb.agent.service.AgentAccountService;
import com.zbkj.crmeb.agent.service.AgentService;
import com.zbkj.crmeb.agent.vo.AgentVo;
import com.zbkj.crmeb.chant.model.ChannelMerchant;
import com.zbkj.crmeb.chant.service.IChannelMerchantService;
import com.zbkj.crmeb.enums.StockAreaTempEnum;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 服务商表 服务实现类
 * </p>
 *
 * @author wuzp
 * @since 2022-02-15
 */
@Service
public class AgentServiceImpl extends ServiceImpl<AgentDao, Agent> implements AgentService {

    @Autowired
    AgentDao agentDao;
    @Autowired
    AgentAccountService agentAccountService;
    @Autowired
    IChannelMerchantService channelMerchantService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<String> addAgent(AddAgentRequest request) {
        Agent agent = new Agent();
        AgentAccount agentAccount = new AgentAccount();
        BeanUtils.copyProperties(request, agent,"id");
        BeanUtils.copyProperties(request, agentAccount,"id");
        if(request.getParentId() != 0 ){
            if(Optional.ofNullable(this.getById(request.getParentId())).orElse(new Agent()).getParentId() != 0){
                throw new CrmebException("上级服务商不是一级服务商");
            }
            validatedAgent(agent,request);
        }
        save(agent);
        agentAccount.setAgentId(agent.getId());
        agentAccountService.save(agentAccount);
        return CommonResult.success();
    }

    public void validatedAgent(Agent agent,AddAgentRequest request) {
        if(dataAccess(agent.getBrandIds(), request.getBrandIds())){
            throw new CrmebException("可见品牌不能超过一级服务商权限");
        }
        if(dataAccess(agent.getSuppliersIds(), request.getSuppliersIds())){
            throw new CrmebException("可见供应商不能超过一级服务商权限");
        }
        if(dataAccess(agent.getTempId(), request.getTempId())){
            throw new CrmebException("发货地不能超过一级服务商权限");
        }
    }

    public boolean dataAccess(String source, String target) {
        List<Integer> agentList = JSONArray.parseArray(source, Integer.class);
        List<Integer> list = JSONArray.parseArray(target, Integer.class);
        if(CollectionUtils.isNotEmpty(agentList) && CollectionUtils.isEmpty(list) ){
            return true;
        }
        if(CollectionUtils.isNotEmpty(agentList) && CollectionUtils.isNotEmpty(list)){
            return !agentList.containsAll(list);
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<String> updateAgent(AddAgentRequest request) {
        if(request.getId() == null){
            throw new CrmebException("服务商id不能为空");
        }
        Agent agent = this.getById(request.getId());
        if(Objects.isNull(agent) || agent.getIsDel() == 1){
            throw new CrmebException("该服务商不存在");
        }
        //下级权限
        List<Integer> brandList = null,
                supplierList = null,
                tempIdList = null;
        List<ChannelMerchant> merchantList = channelMerchantService.list(Wrappers.lambdaQuery(ChannelMerchant.class).eq(ChannelMerchant::getAgentId, agent.getId()).eq(ChannelMerchant::getIsDel, 0));
        if(CollectionUtils.isNotEmpty(merchantList)){
            brandList = merchantList.stream().noneMatch(e -> e.getBrandIds().equals("[]")) ? merchantList.stream().map(ChannelMerchant::getBrandIds).map(e -> JSONArray.parseArray(e, Integer.class)).flatMap(Collection::stream).distinct().collect(Collectors.toList()) : new ArrayList<>();
            supplierList = merchantList.stream().noneMatch(e -> e.getSuppliersIds().equals("[]")) ? merchantList.stream().map(ChannelMerchant::getSuppliersIds).map(e -> JSONArray.parseArray(e, Integer.class)).flatMap(Collection::stream).distinct().collect(Collectors.toList()) : new ArrayList<>();
            tempIdList = merchantList.stream().noneMatch(e -> e.getTempId().equals("[]")) ? merchantList.stream().map(ChannelMerchant::getTempId).map(e -> JSONArray.parseArray(e, Integer.class)).flatMap(Collection::stream).distinct().collect(Collectors.toList()) : new ArrayList<>();
        }
        if(agent.getParentId() != 0 ){
            Agent superiorAgent = this.getById(agent.getParentId());
            //上级权限
            validatedAgent(superiorAgent,request);
        }else {
            //下级权限
            List<Agent> agentList = this.list(Wrappers.lambdaQuery(Agent.class).eq(Agent::getParentId, agent.getId()).eq(Agent::getIsDel, 0));
            if(CollectionUtils.isNotEmpty(agentList)){
                if(brandList == null || brandList.size() > 0){
                    brandList = agentList.stream().noneMatch(e -> e.getBrandIds().equals("[]")) ? Stream.of(agentList.stream().map(Agent::getBrandIds).map(e -> JSONArray.parseArray(e, Integer.class)).flatMap(Collection::stream).distinct().collect(Collectors.toList()), brandList).filter(Objects::nonNull).flatMap(Collection::stream).distinct().collect(Collectors.toList()) : new ArrayList<>();
                }
                if(supplierList == null || supplierList.size() > 0){
                    supplierList = agentList.stream().noneMatch(e -> e.getSuppliersIds().equals("[]")) ? Stream.of(agentList.stream().map(Agent::getSuppliersIds).map(e -> JSONArray.parseArray(e, Integer.class)).flatMap(Collection::stream).distinct().collect(Collectors.toList()), supplierList).filter(Objects::nonNull).flatMap(Collection::stream).distinct().collect(Collectors.toList()) : new ArrayList<>();
                }
                if(tempIdList == null || tempIdList.size() > 0){
                    tempIdList = agentList.stream().noneMatch(e -> e.getTempId().equals("[]")) ? Stream.of(agentList.stream().map(Agent::getTempId).map(e -> JSONArray.parseArray(e, Integer.class)).flatMap(Collection::stream).distinct().collect(Collectors.toList()),tempIdList).filter(Objects::nonNull).flatMap(Collection::stream).distinct().collect(Collectors.toList()) : new ArrayList<>();
                }
            }
        }
        if(followPermissions(brandList,JSONArray.parseArray(request.getBrandIds(), Integer.class))){
            throw new CrmebException("品牌权限不能小于下级");
        }
        if(followPermissions(supplierList,JSONArray.parseArray(request.getSuppliersIds(), Integer.class))){
            throw new CrmebException("供应商权限不能小于下级");
        }
        if(followPermissions(tempIdList,JSONArray.parseArray(request.getTempId(), Integer.class))){
            throw new CrmebException("发货地权限不能小于下级");
        }
        AgentAccount agentAccount = agentAccountService.getOne(Wrappers.lambdaQuery(AgentAccount.class).eq(AgentAccount::getAgentId, request.getId()));
        if(Objects.isNull(agentAccount)){
            throw new CrmebException("该服务商账户不存在");
        }
        BeanUtils.copyProperties(request, agent);
        updateById(agent);
        BeanUtils.copyProperties(request, agentAccount,"id");
        agentAccountService.updateById(agentAccount);
        return CommonResult.success();
    }

    public boolean followPermissions(List<Integer> source,List<Integer> target) {
        if(source == null){
            return false;
        }
        if(CollectionUtils.isNotEmpty(target)){
            if(CollectionUtils.isEmpty(source)){
                return true;
            }
            return !target.containsAll(source);
        }
        return false;
    }

  @Override
    public CommonResult<String> deleteAgent(Integer id) {
        Agent agent = getById(id);
        if(agent == null){
            throw new CrmebException("该服务商不存在");
        }
        if(agent.getParentId() == 0){
            List<Agent> agentList = this.list(Wrappers.lambdaQuery(Agent.class).eq(Agent::getParentId, id).eq(Agent::getIsDel, 0));
            if(CollectionUtils.isNotEmpty(agentList)){
                throw new CrmebException("该服务商下存在二级服务商,不可删除");
            }
        }
        List<ChannelMerchant> channelMerchantList = channelMerchantService.list(Wrappers.lambdaQuery(ChannelMerchant.class).eq(ChannelMerchant::getAgentId, id).eq(ChannelMerchant::getIsDel, 0));
        if(CollectionUtils.isNotEmpty(channelMerchantList)){
            throw new CrmebException("该服务商下存在商户,不可删除");
        }
        return update(Wrappers.lambdaUpdate(Agent.class).eq(Agent::getId,id).set(Agent::getIsDel,1)) ? CommonResult.success() : CommonResult.failed();
    }

    @Override
    public CommonResult<List<DropDownAgentsResponse>> dropDownAgents(Integer level) {
        List<Agent> agentList = list(Wrappers.lambdaQuery(Agent.class).eq(level == 1, Agent::getParentId, 0).ne(level == 2, Agent::getParentId, 0)
                .eq(Agent::getIsDel, 0).select(Agent::getId,Agent::getAgentName));
        List<DropDownAgentsResponse> responses = agentList.stream().map(e -> new DropDownAgentsResponse().setId(e.getId()).setAgentName(e.getAgentName())).collect(Collectors.toList());
        return CommonResult.success(responses);
    }

    @Override
    public PageInfo<AgentVo> getFinancialAgentList(AgentListRequest request) {
        Page<Agent> page = PageHelper.startPage(request.getPage(), request.getLimit());
        if(request.getAccountStart() != null && request.getAccountEnd() != null) {
            if (request.getAccountStart().compareTo(request.getAccountEnd()) > 0) {
                throw new CrmebException("最小金额不能大于最大金额！");
            }
        }
        if(request.getCreateTimeStart() != null && request.getCreateTimeEnd() != null) {
            if (request.getCreateTimeStart().compareTo(request.getCreateTimeEnd()) > 0) {
                throw new CrmebException("开始时间不能大于结束时间！");
            }
        }
        List<AgentVo> agentVoList = agentDao.getAgentVoList(request);
        return CommonPage.copyPageInfo(page, agentVoList);
    }

    @Override
    public CommonResult<AgentVo> getAgentById(Integer id) {
        Agent agent = getById(id);
        if(agent == null){
            throw new CrmebException("该服务商不存在");
        }
        AgentAccount agentAccount = agentAccountService.getOne(Wrappers.lambdaQuery(AgentAccount.class).eq(AgentAccount::getAgentId, id));
        if(agentAccount == null){
            throw new CrmebException("该服务商账户不存在");
        }
        AgentVo response = new AgentVo();
        BeanUtils.copyProperties(agentAccount,response,"id");
        BeanUtils.copyProperties(agent,response);
        if(agent.getParentId() != 0){
            Agent ParentAgent = Optional.ofNullable(getById(agent.getParentId())).orElse(new Agent());
            response.setParentAgentName(ParentAgent.getAgentName());
            response.setHigherBrandIds(ParentAgent.getBrandIds());
            response.setHigherSuppliersIds(ParentAgent.getSuppliersIds());
            response.setHigherTempId(ParentAgent.getTempId());
        }
        return CommonResult.success(response);
    }

    @Override
    public PageInfo<Agent> getAgentList(PageParamRequest request) {
        Page<Agent> page = PageHelper.startPage(request.getPage(), request.getLimit());
        List<Agent> agentList = this.list(Wrappers.lambdaQuery(Agent.class).eq(Agent::getIsDel, 0).eq(Agent::getParentId, 0).orderByAsc(Agent::getId));
        if(CollectionUtils.isNotEmpty(agentList)){
            List<Agent> secondAgentList = this.list(Wrappers.lambdaQuery(Agent.class).eq(Agent::getIsDel, 0).in(Agent::getParentId,agentList.stream().map(Agent::getId).collect(Collectors.toList())).orderByAsc(Agent::getId));
            Map<Integer, List<Agent>> agentMap = secondAgentList.stream().collect(Collectors.groupingBy(Agent::getParentId));
            agentList.forEach(e->{
                e.setSecondAgentList(agentMap.get(e.getId()));
            });
        }
        return CommonPage.copyPageInfo(page, agentList);
    }

    @Override
    public List<SettlementResponse> settlement(SettlementRequest request) {
        if(request.getStartTime() != null && request.getEndTime() != null) {
            if (request.getStartTime().compareTo(request.getEndTime()) > 0) {
                throw new CrmebException("开始时间不能大于结束时间！");
            }
        }
        PageHelper.startPage(request.getPage(), request.getLimit());
        return agentDao.getSettlement(request);
    }

    /**
     * 管理员服务商下拉框
     * @param request
     * @return
     */
    @Override
    public CommonResult<List<DropDownAgentsResponse>> listDropDownAgents(AdminAgentRequest request) {
        List<Agent> agentList = list(Wrappers.lambdaQuery(Agent.class)
                .eq(1 == request.getAgentLevel(), Agent::getParentId, 0)
                .ne(2 == request.getAgentLevel(), Agent::getParentId, 0)
                .in(2 == request.getAgentLevel() && CollectionUtils.isNotEmpty(request.getParentIds()), Agent::getParentId, request.getParentIds())
                .eq(Agent::getIsDel, 0)
                .select(Agent::getId, Agent::getAgentName));
        List<DropDownAgentsResponse> responses = agentList.stream().map(e -> new DropDownAgentsResponse().setId(e.getId()).setAgentName(e.getAgentName())).collect(Collectors.toList());
        return CommonResult.success(responses);
    }

    /**
     * 查询一级服务商下二级服务商id
     *
     * @param oneAgentIds
     * @return
     */
    @Override
    public List<Integer> listTwoAgentIds(List<Integer> oneAgentIds) {
        List<Agent> agentList = list(Wrappers.lambdaQuery(Agent.class)
                .ne(Agent::getParentId, 0)
                .in(Agent::getParentId, oneAgentIds)
                .eq(Agent::getIsDel, 0)
                .select(Agent::getId));
        return agentList.stream().map(Agent::getId).collect(Collectors.toList());
    }

    /**
     * 服务商发货地
     * @return
     */
    @Override
    public List<StockAreaTempEnum> getStockArea(Integer agentId) {
        Agent agent = Optional.ofNullable(getById(agentId)).orElse(new Agent());
        JSONArray tempJson = JSONArray.parseArray(agent.getTempId());
        List<StockAreaTempEnum> stockAreaTempEnumList = null;
        if(!tempJson.isEmpty()){
            List<Integer> tempList = tempJson.toJavaList(Integer.class);
            stockAreaTempEnumList = tempList.stream().map(StockAreaTempEnum::valueOf).collect(Collectors.toList());
        }
        return stockAreaTempEnumList;
    }
}
